#!/usr/local/bin/python2.7
# encoding: utf-8
'''
NervuresDesignTool -- Outil de conception/simulation de parapentes Nervures
Classe xxx
Description :
@module : graphics.view
@author:      puiseux
@copyright:   2013 Nervures. All rights reserved.      
@license:    LGPL
@contact:    be@nervures.com, pierre@puiseux.name
@deffield    creation: 19 janv. 2013
'''
import sys
import math
from PyQt4 import QtCore, QtGui
from PyQt4.uic import loadUiType
from PyQt4.Qt import SIGNAL
import numpy as np
from graphics.scene import EGraphicsScene
# from graphics.polygon import NGraphicsPolygonItem 
from graphics.graphicsprofil import EGraphicsProfilItem
# from graphics.ellipse import NGraphicsEllipseItem
from graphics.node import Noeud
from graphics.preferences import ViewPrefs, ScenePrefs
from utilitaires import whoami, Path, trace
from config import SOURCES_DIR
from model.profil import EProfil

#EGraphicsView = QtGui.QGraphicsView
class EGraphicsView(QtGui.QGraphicsView):
    """
    La vue graphique (seule, sans outils) commune à tous les widget graphiques 2d.
    La QGraphicsView recoit et traite les évènement (events souris, clavier, ..) 
    et les transforme en coordonnées scene avant de les passer à la QGraphicsScene.
    Elle est la vue (en terme View/Model).
    Elle peut redéfinir les event-handler (mousePressEvent(),...xxxEvent())  
    Elle les passe ensuite (s'ils ne sont pas redéfinis) dans l'ordre aux
        - QGraphicsScene -> peuvent aussi réimplémenter les event-handlers
        - QGraphicsItems concernés-> peuvent accepter ou non les events avec QGraphicsItem.setAcceptXXX()
        - QWidget conteneur -> peuvent réimplémenter les event-handlers
    Les évènements souris sont transmis au 'mouse-grabber' : l'item sur lequel la souris a pressé (sans relacher)
    Les évènements clavier sont trasmis au 'focus-item', l'item qui a le focus (retourné par focusItem())

    """
    prefs = ViewPrefs()
    def __init__(self, parent=None):
        super(EGraphicsView, self).__init__(parent)
        self.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
        self.setRubberBandSelectionMode(QtCore.Qt.ContainsItemShape)
        self.setRenderHint(QtGui.QPainter.Antialiasing)
        self.setRenderHint(QtGui.QPainter.TextAntialiasing)
        self.scale(1,-1)
        self.setInfosViewer()
        self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
        self.setBackgroundBrush(self.prefs.BACKGROUND_BRUSH)
        self.setForegroundBrush(self.prefs.FOREGROUND_BRUSH)
        self.grid = False
#        self.addSliderForSmoothing()
#    def setInfosViewer(self, textedit):
#        self.infosviewer = textedit
    def setInfosViewer(self):
#        infosviewer = QtGui.QLabel(self.parent())#fenetre a part
        infosviewer = QtGui.QLabel(self.parentWidget())#fenetre separee
        #infosviewer = QtGui.QLabel(self)#dans la scene
        infosviewer.setMargin(10)
        infosviewer.setFont(QtGui.QFont("Serif", 10))
        self.infosviewer = infosviewer
#        self.infosviewer.setBaseSize(QtCore.QSize())
    
    def drawBackground(self, painter, rect):
        painter.setBrush(ScenePrefs.BACKGROUND_BRUSH)
        painter.setPen(ScenePrefs.RECT_PEN)
        
    def showGrid(self, value):
        self.grid = value

    def drawForeground(self, painter, rect) :
        '''
        Source C++
        painter->setWorldMatrixEnabled(true);//inutile?
        
        qreal left = int(rect.left()) - (int(rect.left()) % m_gridSize);
        qreal top = int(rect.top()) - (int(rect.top()) % m_gridSize);
        
        QVarLengthArray<QLineF, 100> linesX;
        for (qreal x = left; x < rect.right(); x += m_gridSize)
            linesX.append(QLineF(x, rect.top(), x, rect.bottom()));
        
        QVarLengthArray<QLineF, 100> linesY;
        for (qreal y = top; y < rect.bottom(); y += m_gridSize)
            linesY.append(QLineF(rect.left(), y, rect.right(), y));
        if (m_grid == true && linesY.size()<50)
        {
            painter->setPen(m_gridColour);
            painter->drawLines(linesX.data(), linesX.size());
            painter->drawLines(linesY.data(), linesY.size());
        }
        '''
        
        interval = 1#interval to draw grid lines at
#         painter.setWorldMatrixEnabled(True)#
        painter.setPen(self.prefs.FOREGROUND_PEN)
        left = int(rect.left()) - (int(rect.left()) % interval)
        top  = int(rect.top()) - (int(rect.top()) % interval )

        self.linesX = []#QtCore.QVarLengthArray <QLineF, 100> linesX;
        for x in np.arange(left, rect.right(), interval) :
            self.linesX.append(QtCore.QLineF(x, rect.top(), x, rect.bottom()))
        self.linesY = []#QtCore.QVarLengthArray <QLineF, 100> linesX;
        for y in np.arange(top, rect.bottom(), interval) :
            self.linesX.append(QtCore.QLineF(rect.left(), y, rect.right(), y))

        if self.grid : 
            painter.drawLines(self.linesX)
            painter.drawLines(self.linesY)
            painter.setPen(self.prefs.AXES_PEN)
            painter.drawLine(QtCore.QLineF(rect.left(), 0, rect.right(), 0))
            painter.drawLine(QtCore.QLineF(0, rect.top(), 0, rect.bottom()))
#         else : 
#             self.update()
#             for line in self.linesX : line.hide()
#             for line in self.linesY : line.hide()
            
    def wheelEvent(self, event):
        scale = math.pow(2.0, -event.delta() / 240.0)
        self.scale(scale, scale)
        self.update()
#
    def scaleView(self, scaleFactor):
        self.scale(scaleFactor, scaleFactor)
#    def keyPressEvent(self, event):
#        key = event.key()
#        trace(self, key)
#        if key == QtCore.Qt.Key_V : 
#            self.cb_verrouiller.toggle()
#        elif key == QtCore.Qt.Key_N : 
#            self.cb_pnumpts.toggle()
#        elif key == QtCore.Qt.Key_L :
#            self.gb_lissage.setChecked(not self.gb_lissage.isChecked())
#        return super(EGraphicsView, self).keyPressEvent(event)    
    
    def showInfos(self, infos):
        pos = self.infosviewer.pos()
        self.infosviewer.hide()
        self.infosviewer.setText(infos)
        self.infosviewer.move(pos)
        self.infosviewer.show()
    
    def setScene(self, scene):
        try : self.connect(self.hs_tension, SIGNAL('sliderReleased()'), scene.setTension)
        except AttributeError : 
            #trace(self, '###TODO: Bouger cette connexion de la !!!!')
            pass
        self.scene = scene
        return super(EGraphicsView, self).setScene(scene)

if __name__ == "__main__":
    from config import VALIDATION_DIR
#    from utilitaires.path import Path
    fprofil = Path(VALIDATION_DIR, "unenervure2d.gnu")
    fprofil = Path(VALIDATION_DIR, "simple", "simple2d2.gnu")
    points = []
    for line in open(fprofil).readlines() :
        if not line or line[0]=='#' : continue
        else : 
            points.append ([100*float(v) for v in line.strip().split()])
    
    app = QtGui.QApplication(sys.argv)       
#    p = NGraphicsPolygonItem(points)
#    p = NGraphicsProfilItem(points)
    p = EGraphicsProfilItem(points[:-1])
#    ellipse = NGraphicsEllipseItem()
#    base = Noeud([1.0,3.0])
#    fils = BoundedNode([1, 2], base)
#    nodes = [Noeud([10, 20]), BoundedNode([20, 30], base)]
#    nodes.extend([BoundedNode([100, 500], base), BoundedNode([200, 500], base)])
#     ellipse = NGraphicsEllipseItem(0,0,2,3)
    scene = EGraphicsScene(None)
    scene.addItem(p)
#    scene.addItem(q)
#    scene.addItem(base)
#    for node in nodes : scene.addItem(node)
#     scene.addItem(ellipse)
#    widget = NGraphicsEditWidget()
    scene.recadre()
    widgetview = EGraphicsView()
#    widgetview.scale(1,-1)
    widgetview.setScene(scene)
#    widget.resize(1080,800)
#    widgetview.recadre()
    widgetview.show()
    sys.exit(app.exec_())
    